package com.zlf.sshtools.portforward;

import cn.hutool.core.util.StrUtil;
import cn.hutool.log.Log;
import com.zlf.sshtools.utils.AlertUtils;
import java.net.URL;
import java.util.ResourceBundle;
import javafx.concurrent.Task;
import javafx.fxml.FXML;
import javafx.fxml.Initializable;
import javafx.scene.Node;
import javafx.scene.control.Button;
import javafx.scene.control.CheckBox;
import javafx.scene.control.Label;
import javafx.scene.control.TextField;
import javafx.scene.layout.FlowPane;
import javafx.scene.layout.VBox;

public class PortforwardController implements Initializable {

    private PortforwardService service = new PortforwardService();
    private static final Log LOG = Log.get();

    @FXML
    private VBox vbox;

    @FXML
    private void add() {
        createPane(new PortforwardVO());
    }

    private PortforwardVO handleSaveBtn(FlowPane pane) {
        PortforwardVO vo = new PortforwardVO();
        Object id = pane.getUserData();
        if (id != null) {
            vo.id = (String) id;
        }

        pane.getChildren().forEach(node -> {
            if (node instanceof TextField) {
                TextField tf = (TextField) node;
                String val = StrUtil.nullToDefault(tf.getText(), "");
                switch (tf.getId()) {
                    case "name":
                        vo.name = val;
                        break;
                    case "localPort":
                        vo.localPort = Integer.parseInt(val);
                        break;
                    case "remotePort":
                        vo.remotePort = Integer.parseInt(val);
                        break;
                    case "remoteHost":
                        vo.remoteHost = val;
                        break;
                    case "sshHost":
                        vo.sshHost = val;
                        break;
                    case "sshUser":
                        vo.sshUser = val;
                        break;
                    case "sshPassword":
                        vo.sshPassword = val;
                        break;
                    case "socksProxy":
                        vo.socksProxy = val;
                        break;
                }
            } else if (node instanceof CheckBox) {
                CheckBox cb = (CheckBox) node;
                switch (cb.getId()) {
                    case "autostart":
                        vo.autostart = cb.isSelected();
                        break;
                }
            }
        });
        service.save(vo);
        pane.setUserData(vo.id);
        AlertUtils.info("保存成功。");
        handleStopBtn(pane);
        if (vo.autostart) {
            start(pane);
        }
        return vo;
    }

    private void handleDelBtn(FlowPane pane) {
        Object id = pane.getUserData();
        if (id != null) {
            handleStopBtn(pane);
            service.del((String) id);
        }
        vbox.getChildren().remove(pane);
    }

    private void handleStartBtn(FlowPane pane) {
        PortforwardVO vo = handleSaveBtn(pane);
        if (vo.autostart) {
            return;
        }
        start(pane);
    }

    private void start(FlowPane pane) {
        new Thread(new Task<Void>() {
            @Override
            protected Void call() throws Exception {
                try {
                    service.start(pane.getUserData().toString());
                } catch (Exception e) {
                    LOG.error(e, "端口转发启动失败,name:{}", pane.getUserData());
                    throw e;
                }
                return null;
            }

            @Override
            protected void succeeded() {
                getButtonById(pane, "start").setDisable(true);
                getButtonById(pane, "stop").setDisable(false);
            }

            @Override
            protected void failed() {
                AlertUtils.warnning("启动失败！");
            }
        }).start();
    }

    private void handleStopBtn(FlowPane pane) {
        Object id = pane.getUserData();
        if (id == null) {
            AlertUtils.warnning("请先保存。");
            return;
        }
        new Thread(new Task<Void>() {
            @Override
            protected Void call() throws Exception {
                service.stop((String) id);
                return null;
            }

            @Override
            protected void succeeded() {
                getButtonById(pane, "start").setDisable(false);
                getButtonById(pane, "stop").setDisable(true);
            }

            @Override
            protected void failed() {
                AlertUtils.warnning("停止失败！");
            }

        }).start();
    }

    private Button getButtonById(FlowPane pane, String id) {
        for (Node node : pane.getChildren()) {
            if (node instanceof Button) {
                Button btn = (Button) node;
                if (StrUtil.equals(id, btn.getId())) {
                    return btn;
                }
            }
        }
        return null;
    }

    @Override
    public void initialize(URL location, ResourceBundle resources) {
        service.getAll().forEach(it -> {
            createPane(it);
        });
    }

    private void createPane(PortforwardVO vo) {
        FlowPane pane = new FlowPane();
        pane.setUserData(vo.id);
        pane.getChildren().add(new Label("名称"));
        TextField name = new TextField(vo.name);
        name.setId("name");
        pane.getChildren().add(name);
        pane.getChildren().add(new Label("远程主机"));
        TextField remoteHost = new TextField(vo.remoteHost);
        remoteHost.setId("remoteHost");
        pane.getChildren().add(remoteHost);
        pane.getChildren().add(new Label("远程端口"));
        TextField remotePort = new TextField(String.valueOf(vo.remotePort));
        remotePort.setId("remotePort");
        pane.getChildren().add(remotePort);
        pane.getChildren().add(new Label("本地端口"));
        TextField localPort = new TextField(String.valueOf(vo.localPort));
        localPort.setId("localPort");
        pane.getChildren().add(localPort);
        pane.getChildren().add(new Label("转发主机"));
        TextField sshHost = new TextField(vo.sshHost);
        sshHost.setId("sshHost");
        pane.getChildren().add(sshHost);
        pane.getChildren().add(new Label("转发主机账号"));
        TextField sshUser = new TextField(vo.sshUser);
        sshUser.setId("sshUser");
        pane.getChildren().add(sshUser);
        pane.getChildren().add(new Label("转发主机密码"));
        TextField sshPassword = new TextField(vo.sshPassword);
        sshPassword.setId("sshPassword");
        pane.getChildren().add(sshPassword);
        pane.getChildren().add(new Label("SOCKS代理地址"));
        TextField socksProxy = new TextField(vo.socksProxy);
        socksProxy.setId("socksProxy");
        pane.getChildren().add(socksProxy);
        CheckBox autostart = new CheckBox("自动启动");
        autostart.setId("autostart");
        autostart.setSelected(vo.autostart);
        pane.getChildren().add(autostart);
        Button saveBtn = new Button("保存");
        saveBtn.setOnMouseClicked(event -> {
            handleSaveBtn(pane);
        });
        pane.getChildren().add(saveBtn);
        Button delBtn = new Button("删除");
        delBtn.setOnMouseClicked(event -> {
            handleDelBtn(pane);
        });
        pane.getChildren().add(delBtn);
        Button startBtn = new Button("启动");
        startBtn.setDisable(true);
        startBtn.setId("start");
        startBtn.setOnMouseClicked(event -> {
            handleStartBtn(pane);
        });
        pane.getChildren().add(startBtn);
        Button stopBtn = new Button("停止");
        stopBtn.setDisable(true);
        stopBtn.setId("stop");
        stopBtn.setOnMouseClicked(event -> {
            handleStopBtn(pane);
        });
        pane.getChildren().add(stopBtn);
        vbox.getChildren().add(pane);

        if (StrUtil.isBlank(vo.id)) {
            return;
        }

        if (vo.autostart) {
            start(pane);
        } else {
            startBtn.setDisable(false);
        }
    }
}
